home *** CD-ROM | disk | FTP | other *** search
/ Amiga Collections: Taifun / Taifun 054 (1988-05-15)(Ossowski, Stefan)(DE)(PD).zip / Taifun 054 (1988-05-15)(Ossowski, Stefan)(DE)(PD).adf / MRBackup / MRBackup2.0 / Restore.c < prev    next >
C/C++ Source or Header  |  1988-04-09  |  10KB  |  390 lines

  1. /* Filename:    restore.c
  2.  * Author:        Mark R. Rinfret
  3.  * Date:        08/02/87
  4.  * Description:    Restore processing module for MRBackup
  5.  *
  6.  * History:        (most recent change first)
  7.  *
  8.  * 12/18/87 -MRR- Restore was using function IsCompressed() to determine
  9.  *                candidates for decompression.  Unfortunately, it also
  10.  *                tried to decompress .ARC and .ZOO files.
  11.  *
  12.  *                  Restore now requests the next disk to be restored from.
  13.  *
  14.  * 11/22/87 -MRR- Modifications for version 2.0.
  15.  *
  16.  * 09/19/87 -MRR- Added NewHomeDir() which creates subdirectories as
  17.  *                necessary when the initial backup path specifies a
  18.  *                subdirectory.
  19.  */
  20.  
  21.  
  22. #include "MRBackup.h"
  23. #include ":src/lib/DiskMisc.h"
  24.  
  25. char fullBackPath[PATH_MAX+1], fullHomePath[PATH_MAX+1];
  26. static BOOL bigFileSeqNbr;        /* >0 => big file sequence number */
  27. BOOL homeIsDevice;        /* true => home is "DH<N>:" */
  28.  
  29. ^L
  30. /* Create a new directory on the home device.
  31.  * Called with:
  32.  *        name:        directory pathname
  33.  * Returns:
  34.  *        false => success
  35.  *        true  => failure
  36.  */
  37. int
  38. NewHomeDir(name)
  39.     char   *name;
  40. {
  41.     char c;
  42.     struct Lock *dirLock;
  43.     int dirLeng;
  44.     int errnum;
  45.     char dirname[256];
  46.     int nameindx = 0, nameleng;
  47.  
  48.     *dirname = '\0';
  49.     dirLeng = 0;
  50.     nameleng = strlen(name);
  51.  
  52.     /* Parse the pathname, one directory node at a time, creating
  53.      * directories as needed.
  54.      */
  55.  
  56.     while (nameindx < nameleng) {
  57.         if (nameindx)                /* 2nd - nth pass? */
  58.             dirname[dirLeng++] = '/'; /* directory separator */
  59.         while ((c = name[nameindx++]) && c != '/')
  60.             dirname[dirLeng++] = c;
  61.         dirname[dirLeng] = '\0';    /* terminate with null */
  62.         if (dirLock = (struct Lock *)
  63.             Lock(dirname,SHARED_LOCK)) /* subdir exists? */
  64.             UnLock(dirLock);
  65.         else {                        /* create subdirectory */
  66.             if ((dirLock = (struct Lock *) CreateDir(dirname))== NULL){
  67.                 if ((errnum = IoErr())== ERROR_DIRECTORY_NOT_EMPTY){
  68.                     sprintf(conmsg,
  69.                         "Directory %s already exists!\n",dirname);
  70.                     TypeAndSpeak(conmsg);
  71.                 }
  72.                 else {
  73.                     sprintf(conmsg,
  74.                         "ERROR %d: Unable to create directory %s\n",
  75.                         errnum,dirname);
  76.                     TypeAndSpeak(conmsg);
  77.                     return errnum;
  78.                 }
  79.             }
  80.             else
  81.                 UnLock(dirLock);
  82.         }
  83.     }                                /* endwhile */
  84.     return 0;
  85. }
  86. /* Restore files from floppy disk. */
  87.  
  88. int
  89. Restore()
  90. {
  91.     int disks=0, status = 0;
  92.     char volumeName[31];
  93.  
  94.     Speak("And away we go!");
  95.  
  96.     BreakPath(backPath, srcVol, srcPath);
  97.     strcat(srcVol, ":");
  98.  
  99.     homeIsDevice = (homePath[strlen(homePath)-1] == ':');
  100.     BreakPath(homePath, destVol, destPath);
  101.     strcat(destVol, ":");
  102.  
  103.     while ( !status ) {
  104.         TypeAndSpeak("I am ready to read the next disk.\n");
  105.         if (!RequestDisk(mainWindow, srcVol, 
  106.                          "Insert the next disk to be restored in ")) 
  107.             break;
  108.  
  109.         if (!IsDir(backPath)) {
  110.             TypeAndSpeak(
  111.                 "Backup path must be a device or directory name!\n");
  112.             return ERR_ABORT;
  113.         }
  114.         GetVolumeName(srcVol, volumeName);
  115.         SetCurVolumeGadget(volumeName);
  116.         if ( (totalSize = TotalDiskBlocks(destVol)) < 0)
  117.             status = -totalSize;
  118.         else if ((bigFileSeqNbr = GetBigFileInfo(srcVol)) < 0)
  119.             status = -bigFileSeqNbr;
  120.         else {
  121.             status = RestoreFile(srcPath);
  122.         }
  123.         if (bigFileSeqNbr) {        /* we have a big file to restore? */
  124.             status = RestoreBigFile();
  125.         }
  126. /*!!! Need GetErrOpt right here... */
  127.  
  128.         ++disks;
  129.     }
  130.     if (status == 0) {
  131.         if (disks)
  132.             TypeAndSpeak("Your restoration project is completed.\n");
  133.         else
  134.             TypeAndSpeak("Maybe you will let me do it next time.\n");
  135.     }
  136.     else {
  137.         sprintf(conmsg,"Restore terminated with status %d.\n",status);
  138.         TypeAndSpeak(conmsg);
  139.         TypeAndSpeak(
  140.             "Perhaps you should check things out and try it again.\n");
  141.     }
  142.  
  143.     SetCurVolumeGadget("");
  144.     return status;
  145. }
  146. ^L
  147. /* Restore all the files in a directory.
  148.  * Called with:
  149.  *        lock:        lock on the directory
  150.  *        fib:        pointer to file info block
  151.  *        path:        directory pathname (without volume)
  152.  * Returns:
  153.  *        status (0 => success)
  154.  */
  155. int
  156. RestoreDir(lock, fib, path)
  157.     struct Lock *lock; struct FileInfoBlock *fib; char *path;
  158. {
  159.     struct Lock *dirLock = NULL, *filelock = NULL;
  160.     char newpath[256];
  161.     int status = 0;
  162.  
  163.     strcpy(temp, homePath);
  164.     if (*path) {
  165.         if (!homeIsDevice) strcat(temp, "/");
  166.         strcat(temp, path);
  167.     }
  168. #ifdef DEBUG
  169.     sprintf(debugMsg,"Checking for directory %s\n",temp);
  170.     DebugWrite(debugMsg);
  171. #endif
  172.     if (!(dirLock = (struct Lock *) Lock(temp, SHARED_LOCK))) {
  173.         if ((status = IoErr()) == ERROR_OBJECT_NOT_FOUND) {
  174. #ifdef DEBUG
  175.             sprintf(debugMsg,"Creating directory %s\n",temp);
  176.             DebugWrite(debugMsg);
  177. #endif
  178.             if (status = NewHomeDir(temp))
  179.                 return status;
  180.         }
  181.         else {
  182.             sprintf(conmsg,"RestoreDir cannot lock %s: %d\n",temp, status);
  183.             TypeAndSpeak(conmsg);
  184.             return status;
  185.         }
  186.     }
  187.     if (dirLock) UnLock(dirLock);
  188.  
  189.     while (ExNext(lock,fib)) {
  190.         strcpy(newpath, path);
  191.         if (*newpath)
  192.             strcat(newpath, "/");
  193.         strcat(newpath, fib->fib_FileName);
  194.         if (status = RestoreFile(newpath)) {
  195.  
  196.             /* filter out "permissable:" errors */
  197.  
  198.             if (status == ERROR_OBJECT_IN_USE ||
  199.                 status == ERROR_WRITE_PROTECTED)
  200.                 status = 0;
  201.             else
  202.                 break;
  203.         }
  204.     }
  205. done:
  206.     return status;
  207. }
  208. ^L
  209. /* Restore one or more files according to the calling pathname.
  210.  * The path argument does not contain the backup volume name.
  211.  */
  212. int
  213. RestoreFile(path)
  214.     char *path;
  215. {
  216.     struct FileInfoBlock *fib = NULL, *fib2 = NULL;
  217.     UBYTE exists = FALSE, ignore = FALSE;
  218.     unsigned isCompressed;
  219.     struct Lock *lock = NULL;
  220.     USHORT nameLength;
  221.     char *s;
  222.     UBYTE savechar;
  223.     int status = 0;
  224.  
  225.     if (status = CheckStop()) return status;
  226.  
  227.     /* Don't restore the big file here...it's done last. */
  228.  
  229.     if (ThisIsBigFile(path)) return status;
  230.  
  231.     if (!(fib = (struct FileInfoBlock *)
  232.         AllocMem((long) sizeof (struct FileInfoBlock), 
  233.                     MEMF_PUBLIC | MEMF_CHIP))) {
  234.         TypeAndSpeak("RestoreFile could not allocate FIB!\n");
  235.         return ERROR_NO_FREE_STORE;
  236.     }
  237.  
  238.     sprintf(fullBackPath, "%s%s",srcVol,path);
  239.     strcpy(fullHomePath, homePath);
  240.     if (*path) {
  241.         if (!homeIsDevice) strcat(fullHomePath, "/");
  242.         strcat(fullHomePath, path);
  243.     }
  244.  
  245. #ifdef DEBUG
  246.     sprintf(conmsg,"fullBackPath = %s\n",fullBackPath);
  247.     DebugWrite(conmsg);
  248.     sprintf(conmsg,"fullHomePath = %s\n",fullHomePath);
  249.     DebugWrite(conmsg);
  250. #endif
  251.  
  252.     if ((sizeLeft = DiskBlocksLeft(destVol)) < 0) {
  253.         status = -sizeLeft;
  254.         sprintf(conmsg,
  255.             "Can't determine disk blocks left on %s; error %d.\n",
  256.             destVol, status);
  257.         TypeAndSpeak(conmsg);
  258.         goto done;
  259.     }
  260.     SetGauge(sizeLeft, totalSize);
  261.  
  262.     do {
  263.         status = 0;
  264.         if (!(lock = (struct Lock *) Lock(fullBackPath, SHARED_LOCK))) {
  265.             status = IoErr();
  266.             sprintf(conmsg, "RestoreFile can't lock %s; error %d\n",
  267.                     fullBackPath, status);
  268.             TypeAndSpeak(conmsg);
  269.             goto checkStatus;
  270.         }
  271.  
  272.         if (!Examine(lock, fib)) {
  273.             status = IoErr();
  274.             sprintf(conmsg, "RestoreFile can't examine %s; error %d\n", 
  275.                     fullBackPath, status);
  276.             TypeAndSpeak(conmsg);
  277.             goto checkStatus;
  278.         }
  279.  
  280.         if (fib->fib_DirEntryType > 0) {    /* path is a directory */
  281.             status = RestoreDir(lock, fib, path);
  282.             UnLock(lock);
  283.             lock = NULL;
  284.         }
  285.         else {
  286.             UnLock(lock);
  287.             lock = NULL;
  288.  
  289.             /* Note: though we can use the function IsCompressed to test
  290.              * for potentially compressed files in Backup(), ONLY files
  291.              * compressed with LZW (ending in .z) are candidates for
  292.              * decompression.  The following test looks for these files
  293.              * only.
  294.              */
  295.             isCompressed = false;
  296.             if (doCompress && (s = rindex(fullHomePath,'.'))) {
  297.                 /* look for ".z" ONLY! */
  298.                 if (!strcmpc(s, ".z")) {
  299.                     isCompressed = true;
  300.  
  301.                     /* truncate the destination pathname (remove ".z") */
  302.  
  303.                     nameLength = strlen(fullHomePath);
  304.                     fullHomePath[nameLength-2] = '\0';
  305.                 }
  306.             }
  307.     /*#define NOCOPY*/
  308.     #ifndef NOCOPY
  309.             /* If this file exists, then check its modification date.  If
  310.              * it's newer than the backup, don't replace it.
  311.              */
  312.  
  313.             if ((lock = (struct Lock *) Lock(fullHomePath, SHARED_LOCK))) {
  314.                 if (!(fib2 = (struct FileInfoBlock *)
  315.                     AllocMem((long) sizeof (struct FileInfoBlock), 
  316.                                 MEMF_PUBLIC | MEMF_CHIP))) {
  317.                     TypeAndSpeak("RestoreFile could not allocate FIB!\n");
  318.                     status = ERROR_NO_FREE_STORE;
  319.                     goto done;
  320.                 }
  321.                 Examine(lock, fib2);
  322.                 UnLock(lock);
  323.                 lock = NULL;
  324.                 if (CompareDS(&fib2->fib_Date, &fib->fib_Date) >= 0)
  325.                     ignore = TRUE;
  326.             }
  327.  
  328.             if (ignore) {
  329.                 sprintf(conmsg,
  330.                         "Skipping %s, since home file is current.\n",
  331.                         path);
  332.                 WriteConsole(conmsg);
  333.             }
  334.             else {
  335.                 if (! (doCompress && isCompressed) ) {
  336.     copyfile:
  337.                     sprintf(conmsg,"Copying %s\n", fullBackPath);
  338.                     WriteConsole(conmsg);
  339.                     status = CopyFile(fullBackPath, fullHomePath);
  340.                 }
  341.                 else {
  342.                     sprintf(conmsg, "Decompressing %s\n", fullBackPath);
  343.                     WriteConsole(conmsg);
  344.                     if (status = decompress(fullBackPath, fullHomePath)) {
  345.                         sprintf(conmsg, 
  346.                             "Decompression of %s failed;  status is %d.\n",
  347.                             fullBackPath, status);
  348.                         TypeAndSpeak(conmsg);
  349.                         TypeAndSpeak(
  350.                             "I will try to copy the file, instead.\n");
  351.                         /* restore ".z" to name */
  352.                         fullHomePath[nameLength-2] = '.'; 
  353.                         goto copyfile;
  354.                     }
  355.                     CopyFileDate(fullBackPath, fullHomePath);
  356.                 }
  357.             }
  358.     #endif
  359.         }
  360. checkStatus:
  361.         if (status && status != ERR_ABORT) {
  362.             ++errorCount;
  363.             SetErrorGadget();
  364.             if (status == ERROR_DISK_FULL) {
  365.                     TypeAndSpeak("The destination disk is full.\n");
  366.     /* The following test is pretty kludgy.  It boils down to
  367.      * "If the drive is a DF<x> device, it's removable, therefore the
  368.      *  user can recover from this error by inserting a new diskette."
  369.      */
  370.                 if (toupper(destVol[0]) == 'D' && 
  371.                     toupper(destVol[1]) == 'F') {
  372.                     TypeAndSpeak(
  373.             "Put a new disk in the destination drive and try again.\n");
  374.                 }
  375.                 else {
  376.                     TypeAndSpeak(
  377.                         "You may have to delete some files to continue.");
  378.                 }
  379.             }
  380.             status = GetErrOpt(ERR_ABORT|ERR_RETRY_FILE|ERR_IGNORE);
  381.             if (status == ERR_IGNORE) status = 0;
  382.         }
  383.     } while (status == ERR_RETRY_FILE);
  384. done:
  385.     if (lock) UnLock(lock);
  386.     if (fib) FreeMem(fib, (long) sizeof(struct FileInfoBlock));
  387.     if (fib2) FreeMem(fib2, (long) sizeof(struct FileInfoBlock));
  388.     return status;
  389. }
  390.